package com.kingmed.kmss.admin.modules.sys.controller;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.UUID;
import com.kingmed.kmss.admin.modules.sys.model.SysFile;
import com.kingmed.kmss.admin.modules.sys.service.ISysFileService;
import com.kingmed.kmss.admin.modules.sys.vo.ImageVo;
import com.kingmed.kmss.common.constant.sys.FileBizTypeConstants;
import com.kingmed.kmss.common.constant.common.OperatorConstants;
import com.kingmed.kmss.common.exception.BusinessException;
import com.kingmed.kmss.common.service.sys.RedisService;
import com.kingmed.kmss.common.utils.StringUtils;
import com.kingmed.kmss.common.vo.CommonResponse;
import com.kingmed.kmss.common.vo.CommonResponseHelper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 文件信息 前端控制器
 * </p>
 *
 * @author csw
 * @since 2023-04-17
 */
@Slf4j
@RestController
@RequestMapping("/sys/file")
@Api(tags = "sys系统文件管理")
public class SysFileController {

    @Autowired
    private RedisService redisService;
    @Autowired
    private ISysFileService fileService;

    /**
     * 获取文件信息
     */
    @ApiOperation("获取文件信息")
    @GetMapping("/{fileId}")
    public CommonResponse<SysFile> getInfo(@PathVariable("fileId") String fileId)
    {
        return CommonResponseHelper.success(fileService.getById(fileId));
    }

    /**
     * 获取多个文件信息
     * fileId，以","分割
     */
    @ApiOperation("获取多个文件信息")
    @GetMapping("/list/{fileId}")
    public CommonResponse<List<SysFile>> list(@PathVariable("fileId") String fileId)
    {
        if(StringUtils.isBlank(fileId)){
            throw new BusinessException("fileId is empty");
        }
        List<String> fileIdList =  Arrays.asList(StringUtils.split(fileId, OperatorConstants.DH_KEY));
        return CommonResponseHelper.success(fileService.listByIds(fileIdList));
    }

    /**
     * 文件上传请求
     * bizType 为pub的时候可以不用校验token直接下载，其它类型需要校验token
     */
    @ApiOperation("文件上传请求")
    @PostMapping({"/upload","/upload/{bizType}"})
    public CommonResponse<SysFile> upload(@PathVariable(required = false, value = "bizType") String bizType,
                                          @RequestParam(value = "uploadPath", required = false) String uploadPath,
                                          MultipartFile file)
    {
        if(StringUtils.isBlank(bizType)){
            bizType = FileBizTypeConstants.BIZ_TYPE_COMMON;
        }
        try{
            // 上传并返回访问地址
            SysFile sysFile = null;
            if (StringUtils.isBlank(uploadPath)){
                sysFile = fileService.upload(file, bizType);
            }else {
                sysFile = fileService.upload(file, uploadPath, bizType);
            }
            return CommonResponseHelper.success(sysFile);
        }catch (Exception e){
            log.error("上传文件失败", e);
            return CommonResponseHelper.success(e.getMessage());
        }
    }

    /**
     * 文件上传请求 - base64
     */
    @ApiOperation("文件上传请求 - base64")
    @PostMapping("/uploadFromBase64")
    public CommonResponse<SysFile> uploadFromBase64(@RequestBody @Validated ImageVo imageVo)
    {
        try{
            // 上传并返回访问地址
            SysFile sysFile = fileService.upload(imageVo);
            return CommonResponseHelper.success(sysFile);
        }catch (Exception e){
            log.error("上传文件失败", e);
            return CommonResponseHelper.fail(e.getMessage());
        }
    }

    /**
     * 单个删除文件信息
     */
    @ApiOperation("单个删除文件信息")
    @DeleteMapping("/remove/{fileId}")
    public CommonResponse<Boolean> remove(@PathVariable("fileId") String fileId)
    {
        return CommonResponseHelper.success(fileService.delete(fileId));
    }


    /**
     * 批量删除文件信息
     */
    @ApiOperation("批量删除文件信息")
    @DeleteMapping("/removeBatch/{fileIds}")
    public CommonResponse<Boolean> removeBatch(@PathVariable("fileIds") String fileIds)
    {
        return CommonResponseHelper.success(fileService.delete(StringUtils.str2List(fileIds, OperatorConstants.DH_KEY, true, true)));
    }

    /**
     * 通过文件ID获取token来下载文件
     * token只有10分钟有效期
     * @param fileId
     * @return
     */
    @ApiOperation("通过文件ID获取token来下载文件")
    @GetMapping({"/token/{fileId}"})
    public CommonResponse<String> token(@PathVariable("fileId") String fileId){
        if (StringUtils.isBlank(fileId)){
            throw new BusinessException("fileId is empty");
        }
        String uuid = UUID.fastUUID().toString(true);
        redisService.set(uuid, fileId, 600);
        return CommonResponseHelper.success(uuid);
    }

    /**
     * 通过文件ID集合获取token来下载文件
     * token只有10分钟有效期
     * @param fileIds
     * @return
     */
    @ApiOperation("通过文件ID集合获取token来下载文件")
    @GetMapping({"/tokenBatch"})
    public CommonResponse<String> tokenBatch(@RequestBody List<String> fileIds){
        if (CollUtil.isEmpty(fileIds)){
            throw new BusinessException("fileIds is empty");
        }
        String uuid = UUID.fastUUID().toString(true);
        redisService.set(uuid, fileIds, 600);
        return CommonResponseHelper.success(uuid);
    }

    /**
     * 文件下载请求
     */
    @ApiOperation("文件下载请求")
    @GetMapping({"/downloadToken/{token}"})
    public void downloadToken(@PathVariable("token") String token, HttpServletResponse response)
    {
        if(StringUtils.isBlank(token)){
            throw new BusinessException("token is empty");
        }

        Object fileId = redisService.get(token);
        if(Objects.isNull(fileId)){
            throw new BusinessException("链接失效，请重新获取");
        }
        if(fileId instanceof String){
            downLoadAuth(fileId.toString(), response);
        }else if(fileId instanceof List){
            throw new BusinessException("不支持批量下载");
        }else {
            throw new BusinessException("下载异常");
        }
    }

    /**
     * 文件批量下载并压缩成zip
     */
    @ApiOperation("文件批量下载并压缩成zip")
    @GetMapping("/downLoadBatchToZipByToken/{token}")
    public void downLoadBatchToZipByToken(@PathVariable("token") String token, HttpServletResponse response) throws Exception
    {
        if(StringUtils.isBlank(token)){
            throw new BusinessException("token is empty");
        }

        Object fileIds = redisService.get(token);
        if(Objects.isNull(fileIds)){
            throw new BusinessException("链接失效，请重新获取");
        }
        if(fileIds instanceof List){
            fileService.downLoadBatchToZip((List<String>)fileIds, response);
        }else if(fileIds instanceof String){
            fileService.downLoadBatchToZip(Arrays.asList(fileIds.toString()), response);
        }else {
            throw new BusinessException("下载异常");
        }

    }

    /**
     * 内部文件下载
     * @param fileId
     * @param response
     */
    @ApiOperation("内部文件下载")
    @GetMapping(value = "/downLoadAuth/{fileId}")
    public void downLoadAuth(@PathVariable("fileId") String fileId, HttpServletResponse response){
        fileService.downLoadAuth(response, fileId);
    }

}
